package com.grgbanking.it.common.util;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

public class Converter {


	public Converter() {
	}

	/***
	 * 对象拷贝
	 * @param target 拷贝的目录对象
	 * @param src    拷贝的源对象
	 * @throws Exception
	 */
	public static void convert(Object target, Object src) throws Exception {
		convert(target, src, false);
	}

	/*****
	 * 对象拷贝
	 * @param target 拷贝的目标对象
	 * @param src    拷贝的源对象
	 * @param copyNull 是否拷贝空值
	 * @throws Exception
	 */
	public static void convert(Object target, Object src, boolean copyNull)
			throws Exception {
		if (target == null || src == null) {
			throw new IllegalArgumentException(
					"\u590D\u5236\u5BF9\u8C61\u65F6\u53C2\u6570\u975E\u6CD5\uFF0C\u6E90\u5BF9\u8C61\u6216\u76EE\u7684\u5BF9\u8C61\u4E3A\u7A7A\uFF01");
		} else {
			doConvert(target, src, copyNull, !target.getClass().getName()
					.equals(src.getClass().getName())
					&& (src instanceof Object));
			return;
		}
	}

	/****
	 * 根据属性名获取对象的值,暂没有用到
	 * @param obj    对象
	 * @param prop   属性
	 * @return
	 * @throws Exception
	 */
	public static Object getFieldValue(Object obj, String prop)
			throws Exception {
		StringBuffer methodName = new StringBuffer(64);
		methodName.append("get").append(prop.substring(0, 1).toUpperCase())
				.append(prop.substring(1));
		Method method = obj.getClass().getMethod(methodName.toString(), null);
		return method.invoke(obj, null);
	}
	
	/**
	 * 将Map的值转换到Entity
	 * convertMapToObject
	 * 
	 * @param target
	 * @param src
	 * @return
	 * @throws Exception 
	 * @exception 
	 * @since  1.0.0
	 */
	public static Object convertMapToObject(Object target,Map src,String...booleanParam) throws Exception{
		//获取目标对象的所有方法
		
		Method[] methods = target.getClass().getMethods();
		
		for (int i = 0; i < methods.length; i++) {
			//获取目标对象方法名
			String targetMethodName = methods[i].getName();
			//getter
			if (targetMethodName.startsWith("set")) {
				Class srcType = methods[i].getReturnType();
				
				Class[] params = methods[i].getParameterTypes();
				String key = targetMethodName.substring(3);
				key = key.replaceFirst(key.substring(0,1), key.substring(0,1).toLowerCase());
				Object value = src.get(key);
				
				if (value != null) {
					if(booleanParam.length > 0){
						value = convertValue(key, value, booleanParam);
					}

					methods[i].invoke(target, new Object[] { value });
				} 
				
			}
		}
		
		return target;
	}
	
	private static Object convertValue(String key,Object value,String...booleanParam){
		boolean isBoolean = false;
		for(String param : booleanParam ){
			if(key.equals(param)){
				isBoolean = true;
				break;
			}
		}
		if(isBoolean){
			if(value.toString().equals("1")){
				value = true;
			}else{
				value = false;
			}
		}
		
		return value;
	}

	/****
	 * 对象拷贝
	 * @param target 拷贝的目标对象
	 * @param src	 拷贝的源对象
	 * @param copyNull 是否拷贝空值
	 * @param isModel2Form 是否同一对象
	 * @throws Exception
	 */
	private static void doConvert(Object target, Object src, boolean copyNull,
			boolean isModel2Form) throws Exception {
		//获取源对象的所有方法
		Method methods[] = src.getClass().getMethods();
		//解释源对象的get和set方法
		Map map = parseSourceBean(src, methods);
		//获取目标对象的所有方法
		methods = target.getClass().getMethods();
		for (int i = 0; i < methods.length; i++) {
			//获取目标对象方法名
			String targetMethodName = methods[i].getName();
			//当源对象包含目标对象的方法名
			if (map.containsKey(targetMethodName)) {
				Class targetType = methods[i].getParameterTypes()[0];
				Method srcMethod = (Method) map.get(targetMethodName);
				Object value = srcMethod.invoke(src, null);
				if (value != null) {
					if (value.toString().trim().length() == 0) {
						methods[i].invoke(target,
								new Object[] { isModel2Form ? "" : null });
					} else {
						Class srcType = srcMethod.getReturnType();
						if (!targetType.equals(srcType))
							value = parseParamenter(targetType, srcType, value);
						methods[i].invoke(target, new Object[] { value });
					}
				} else if (copyNull)
					methods[i].invoke(target, new Object[] { isModel2Form ? ""
							: null });
			}
		}

		map.clear();
	}

	
	/****
	 * 解释对象的属性
	 * @param source  需解释的对象
	 * @param methods 解释对象的内部方法
	 * @return
	 * @throws Exception
	 */
	private static Map<?,?> parseSourceBean(Object source, Method methods[])
			throws Exception {
		Map map = new HashMap();
		for (int i = 0; i < methods.length; i++) {
			String method = methods[i].getName();
			if (method.startsWith("get") && !"getClass".equals(method))
				map.put(method.replaceFirst("get", "set"), methods[i]);
		}

		return map;
	}

	/****
	 * 解释方法名并拷贝值
	 * @param targetType 目标对象方法
	 * @param srcType	 源对象方法
	 * @param strValue	 需转换的值
	 * @return
	 * @throws Exception
	 */
	private static Object parseParamenter(Class targetType, Class srcType,
			Object strValue) throws Exception {
		String targetTypeName = targetType.getName();
		Object ret = null;
		if (targetTypeName.equals("java.lang.String")) {
			if (strValue != null) {
				String srcTypeName = srcType.getName();
				if (srcTypeName.equals("java.sql.Timestamp")) {
					String s = strValue.toString();
					int index = s.indexOf(".");
					ret = s.substring(0, index);
				} else {
					ret = strValue;
				}
			}
		} else {
			//是否原始对象
			if (targetType.isPrimitive())
				targetType = primitiveToObject(targetType, targetTypeName);
			if (targetTypeName.startsWith("java.math.")
					|| "java.util.Date".equals(targetTypeName)) {
				Constructor c = targetType
						.getConstructor(new Class[] { "java.lang.String"
								.getClass() });
				ret = c.newInstance(new Object[] { strValue });
			} else {
				if (targetTypeName.equals("java.sql.Timestamp")
						&& strValue != null) {
					String value = strValue.toString().trim();
					int len = value.trim().length();
					if (len > 7 && len < 11)
						value = (new StringBuilder(String.valueOf(value)))
								.append(" 00:00:00.0").toString();
					else if (len > 11 && value.indexOf(".") == -1)
						value = (new StringBuilder(String.valueOf(value)))
								.append(".0").toString();
					strValue = value;
				} else if (targetTypeName.equals("java.sql.Date")
						&& strValue != null) {
					String value = strValue.toString().trim();
					if (value.length() > 10)
						value = value.substring(0, 10);
					strValue = value;
				}
				Method method = targetType.getMethod("valueOf",
						new Class[] { "java.lang.String".getClass() });
				ret = method.invoke(targetType, new Object[] { strValue });
			}
		}
		return ret;
	}

	/***
	 * 解释原始对象
	 * @param targetType
	 * @param targetTypeName
	 * @return
	 * @throws ClassNotFoundException
	 */
	private static Class primitiveToObject(Class targetType,
			String targetTypeName) throws ClassNotFoundException {
		if ("int".equals(targetTypeName))
			targetType = Class.forName("java.lang.Integer");
		else if ("long".equals(targetTypeName))
			targetType = Class.forName("java.lang.Long");
		else if ("float".equals(targetTypeName))
			targetType = Class.forName("java.lang.Float");
		else if ("double".equals(targetTypeName))
			targetType = Class.forName("java.lang.Double");
		else if ("boolean".equals(targetTypeName))
			targetType = Class.forName("java.lang.Boolean");
		else if ("char".equals(targetTypeName))
			targetType = Class.forName("java.lang.Character");
		else if ("byte".equals(targetTypeName))
			targetType = Class.forName("java.lang.Byte");
		return targetType;
	}
	
	/** 
     * 将一个 JavaBean 对象转化为一个  Map 
     * @param bean 要转化的JavaBean 对象 
     * @return 转化出来的  Map 对象 
     * @throws IntrospectionException 如果分析类属性失败 
     * @throws IllegalAccessException 如果实例化 JavaBean 失败 
     * @throws InvocationTargetException 如果调用属性的 setter 方法失败 
     */  
    @SuppressWarnings({ "rawtypes", "unchecked" })  
    public static Map convertBean(Object bean)  
            throws IntrospectionException, IllegalAccessException, InvocationTargetException {  
        Class type = bean.getClass();  
        Map returnMap = new HashMap();  
        BeanInfo beanInfo = Introspector.getBeanInfo(type);  
  
        PropertyDescriptor[] propertyDescriptors =  beanInfo.getPropertyDescriptors();  
        for (int i = 0; i< propertyDescriptors.length; i++) {  
            PropertyDescriptor descriptor = propertyDescriptors[i];  
            String propertyName = descriptor.getName();  
            if (!propertyName.equals("class")) {  
                Method readMethod = descriptor.getReadMethod();  
                Object result = readMethod.invoke(bean, new Object[0]);  
                if (result != null) {  
                    returnMap.put(propertyName, result);  
                } else {  
                    returnMap.put(propertyName, "");  
                }  
            }  
        }  
        return returnMap;  
    }  
}
